/**
 * Copyright (C) 2006 ChangSha Sino-Town Science & Technology CO,.LTD. All rights reserved.
 * Sino-Town PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package wzw.util;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import wzw.beans.CodeNameBean;
import wzw.beans.CodeNameEntity;
import wzw.swing.table.PlainTableModel;

import com.kingcore.director.DirectorConstants;
import com.kingcore.framework.context.ApplicationContext;



/**
 * <p>some public util for java desktop development.
 * 		all util is used for java Components just like JComboBox,JList,JTree,JTable etc.
 * 		use ListModel as dataModel, not vector.</p>
 * @author	WUZEWEN on 2006-3-10
 * @version	1.0
 * @see		Object#equals(java.lang.Object)
 * @see		Object#hashCode()
 * @see		HashMap
 * @since	JDK1.4
 */

public class ComponentUtil {	
	

	public static void main(String[] args) {
		String str = "545kl6.54k655";
		System.out.println(filterUnNumber(str));
	}


	/**
	 * 展开 JTree 的某个TreePath 下面的所有子Node，该方法可以放在ComponentUtil.class中去。
	 * @param tree 需要展开的JTree对象
	 * @param parent 需要展开的TreePath
	 * @param expand true:expand;false:collapse;
	 */
    public void expandAll(JTree tree, TreePath parent, boolean expand) {
        // Traverse children
        TreeNode node = (TreeNode)parent.getLastPathComponent();
        if (node.getChildCount() >= 0) {
            for (Enumeration<?> e=node.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode)e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                expandAll(tree, path, expand);
            }
        }
    
        // Expansion or collapse must be done bottom-up
        if (expand) {
            tree.expandPath(parent);
        } else {
            tree.collapsePath(parent);
        }
    }
    
    public static String filterUnNumber(String str) {  
        // 只允数字  
        String regEx = "[^0-9|.]";  
        Pattern p = Pattern.compile(regEx);  
        Matcher m = p.matcher(str);  
    //替换与模式匹配的所有字符（即非数字的字符将被""替换）  
        return m.replaceAll("").trim();  
    }
    
	/**
	 * 弹出式窗口的父容器
	 */
	private static Component mainFrame = null;

	/**
	 * 当前使用的数据库连接池名称，只会是一个GUI客户端使用，不会有相互改动影响的情况，
	 * 	所以采用 static String.
	 */
	private static String poolName="main";
	
	/**
	 * @param args
	 */
	//public static void main(String[] args) {
	//
	//}


	/******************************************************************
	 * 
	 * 		initialize this class.
	 * 
	 * ****************************************************************/

	/**
	 * @return Returns the poolName.
	 */
	public static String getPoolName() {
		return poolName;
	}

	/**
	 * @param poolName The poolName to set.
	 */
	public static void setPoolName(String poolName) {
		ComponentUtil.poolName = poolName;
	}

	/**
	 * 设置弹出式窗口的父对象。
	 * @param mainFrame
	 */
	public static void setMainFrame(Component mainFrame) {
		ComponentUtil.mainFrame = mainFrame;
	}


	/******************************************************************
	 * 
	 * 			for ComboBox component
	 * Key:ComboBox,Item,ItemCode
	 * 
	 * ****************************************************************/

	/**
	 * 根据一个sql语句初始一个JComboBox对象的列表。
	 * @param comboBox 需要初始的JComboBox对象
	 * @param ps_sql 从数据库取数的sql语句
	 */
	public static void initComboBox(JComboBox comboBox, String ps_sql){

	    Connection conn=null;
	    Statement stmt=null;
	    ResultSet rs=null;
	    DefaultComboBoxModel dcm=null;
	    if(comboBox.getModel() instanceof DefaultComboBoxModel){
	    	dcm=(DefaultComboBoxModel)comboBox.getModel();
	    	dcm.removeAllElements();
	    } else {
	    	dcm=new DefaultComboBoxModel();
	    }
	    
	    try {
			conn=getConnection();
			stmt=conn.createStatement();
			rs=stmt.executeQuery(ps_sql);
			CodeNameBean codeName = null;
			int isDefault ;
			while(rs.next()){
				codeName = new CodeNameBean(rs.getString(1),rs.getString(2));
				dcm.addElement(codeName);
				isDefault = rs.getInt(3);
				if (isDefault==1) {
					dcm.setSelectedItem(codeName);
				}
			}
			comboBox.setModel(dcm);
			
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			try {
				if(rs!=null)
					rs.close();
				if(stmt!=null)
					stmt.close();
				if(conn!=null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}


	/**
	 * 根据一个二维数组初始一个JComboBox对象的列表。
	 * @param comboBox 需要初始的JComboBox对象
	 * @param str2 JComboBox对象所有初始项的二维数组表示
	 */
	public static void initComboBox(JComboBox comboBox, String[][] str2){
		if(str2==null){
			return;
		}
	    DefaultComboBoxModel dcm=null;
	    if(comboBox.getModel() instanceof DefaultComboBoxModel){
	    	dcm=(DefaultComboBoxModel)comboBox.getModel();
	    	dcm.removeAllElements();
	    } else {
	    	dcm=new DefaultComboBoxModel();
	    }
	    
		for (int i = 0; i < str2.length; i++) {
			dcm.addElement( new CodeNameBean(str2[i][0], str2[i][1]) );
		}
		comboBox.setModel(dcm);
	}


	/**
	 * 根据当前代码值来设置JComboBox当前的选择行。
	 * @param comboBox 要设置的JCommboBox对象
	 * @param p_value JComboxBox对象当前的内部值，是CodeName中的code值
	 */
	public static void setSelectedItemByCode(JComboBox comboBox,String p_value){
		if(comboBox==null || p_value==null){
			return;
		}
		for (int i = 0; i < comboBox.getItemCount(); i++) {
			if( ((CodeNameEntity)comboBox.getItemAt(i)).getCode().equals(p_value) ){
				comboBox.setSelectedIndex(i);
				return;
			}
		}
		
	}

	/**
	 * 获取JComboBox当前的选择项的代码值。
	 * @param comboBox 要设置的JCommboBox对象
	 * @return code JComboxBox对象当前的内部值，是CodeName中的code值
	 */
	public static String getSelectedItemCode(JComboBox comboBox){
		if(comboBox==null ||comboBox.getSelectedItem()==null ){
			return null;
		}
		return ((CodeNameEntity)comboBox.getSelectedItem()).getCode();		
	}



	/******************************************************************
	 * 
	 * 			for JList component
	 * Key:List,Item,ItemCode
	 * 
	 * ****************************************************************/
	
	/**
	 * 初始一个JLIst对象的列表。
	 * @param list 需要初始的JList对象
	 * @param ps_sql 从数据库取数的sql语句
	 */
	public static void initListBox(JList list, String ps_sql){

		if (list == null || ps_sql == null) {
			return;
		}
	    Connection conn=null;
	    Statement stmt=null;
	    ResultSet rs=null;
	    
	    DefaultListModel dlm=null;
	    if(list.getModel() instanceof DefaultListModel){
	    	dlm=(DefaultListModel)list.getModel();	
	    	dlm.removeAllElements();
	    }else{
	    	dlm = new DefaultListModel();
	    }
	    
	    int i=0;
	    try {
			conn=getConnection();
			stmt=conn.createStatement();
			rs=stmt.executeQuery(ps_sql);
			while(rs.next()){
				dlm.addElement(new CodeNameBean(rs.getString(1),rs.getString(2),i++) );
			}
			//list.setListData(vector);
			list.setModel( dlm );
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			try {
				if(rs!=null)
					rs.close();
				if(stmt!=null)
					stmt.close();
				if(conn!=null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}		
	}

	/**
	 * <p>获取Jlist对象当前选择的所有行的内部值集合，做为一个Vector对象返回。
	 * 	本方法只用于JList,不用于ComboBox,因为ComboBox不可以多选。</p>
	 * @param list
	 * @return 所有行的内部代码值集合
	 */
	public static Vector<String> getSelectedItemCodes(JList list) {
		if(list==null){
			return null;
		}
		Object[] objs=list.getSelectedValues();
		if(objs==null){
			return null;
		}
		Vector<String> codes=new Vector<String>(objs.length);
		for (int i = 0; i < objs.length; i++) {
			codes.add( ((CodeNameEntity)objs[i]).getCode() );
		}
		return codes;		
	}

	/**
	 * <p>获取Jlist对象所有行的内部值集合，做为一个Vector对象返回。
	 * 	本方法只用于JList,不用于ComboBox,因为ComboBox不可以多选。</p>
	 * @param list 要取值的JList对象
	 * @return codes JList对象所有行的内部值集合
	 */
	public static Vector<String> getAllItemCodes(JList list) {
		if(list==null){
			return null;
		}
		Vector<String> codes=new Vector<String>(list.getModel().getSize());
		for (int i = 0; i < codes.capacity(); i++) {
			codes.add( ((CodeNameEntity)list.getModel().getElementAt(i)).getCode() );
		}
		return codes;		
	}

	/**
	 * 从一个ListBox移动已选择的项到另外一个ListBox.
	 * @param fromList 源ListBox
	 * @param toList 目标ListBox
	 * @param isDelete 是否删除被移动的ListBox的项，默认为false.
	 */
	public static void moveSelectedItems(JList fromList, JList toList, boolean isDelete) {
		Object[] selObjs=fromList.getSelectedValues();
		if(selObjs==null){
			JOptionPane.showMessageDialog( ComponentUtil.mainFrame,"没有选择对象！");
			return;
		}
		DefaultListModel dmlFrom=(DefaultListModel)fromList.getModel();
		DefaultListModel dmlTo  =(DefaultListModel)toList.getModel();
		int length=selObjs.length;
		for (int i = 0; i < length; i++) {
			if(dmlTo.contains(selObjs[i])){
				JOptionPane.showMessageDialog( ComponentUtil.mainFrame,"该项已经选择！");
			}else{
				dmlTo.addElement(selObjs[i]);
			}
			if(isDelete){
				dmlFrom.removeElement(selObjs[i]);
			}
		}
	}

	public static void moveSelectedItems(JList fromList, JList toList) {
		moveSelectedItems(fromList, toList, false);
	}
	
	
	/**
	 * 从一个ListBox移动所有的项到另外一个ListBox.
	 * @param fromList
	 * @param toList
	 * @param isDelete 是否删除被移动的ListBox的项，，默认为false.
	 */
	public static void moveAllItems(JList fromList, JList toList, boolean isDelete) {
		if (fromList==null || toList==null) {
			return;
		}
		DefaultListModel dmlFrom=(DefaultListModel)fromList.getModel();
		DefaultListModel dmlTo  =(DefaultListModel)toList.getModel();
		int length=dmlFrom.size();
		for (int i = 0; i < length; i++) {
			if(!dmlTo.contains(dmlFrom.get(i))){
				dmlTo.addElement(dmlFrom.get(i));
			}
		}
		if(isDelete){
			dmlFrom.removeAllElements();
		}
	}
	public static void moveAllItems(JList fromList, JList toList) {
		moveAllItems(fromList, toList, false);
	}

	/**
	 * 删除ListBox中被选择的项
	 * @param list
	 */
	public static void deleteSelectedItems(JList list) {
		if (list==null) {
			return;
		}
		Object[] selObjs=list.getSelectedValues();
		if(selObjs==null || selObjs.length<1){
			JOptionPane.showMessageDialog( ComponentUtil.mainFrame,"没有选择对象！");
			return;
		}
		DefaultListModel dml=(DefaultListModel)list.getModel();
		for (int i = 0; i < selObjs.length; i++) {
			dml.removeElement(selObjs[i]);
		}
	}

	/**
	 * 删除ListBox中所有的项
	 * @param list
	 */
	public static void deleteAllItems(JList list) {
		((DefaultListModel)list.getModel()).removeAllElements();
	}


	/******************************************************************
	 * 
	 * 			for JTree component.
	 * Key: TreeNode,TreeNodeCode
	 * 
	 * ****************************************************************/	


    /**
     * 
     * Remove the currently selected nodes from tree. 
	 * @param tree the tree for operating.
     */
	public static void deleteSelectedTreeNodes(JTree tree) {
        TreePath[] currentSelection = tree.getSelectionPaths();
        
        if (currentSelection != null) {
        	DefaultMutableTreeNode currentNode = null;
        	MutableTreeNode parent = null;
        	for (int i = 0; i < currentSelection.length; i++) {
        		if(currentSelection[i]==null)
        			continue;
                currentNode = (DefaultMutableTreeNode)(currentSelection[i].getLastPathComponent());
                parent = (MutableTreeNode)(currentNode.getParent());
                if (parent != null) {
                	((DefaultTreeModel)tree.getModel()).removeNodeFromParent(currentNode);       
                }				
			}
        } 
        return;
    }

    /**
     * Add child to the currently selected node. 
     *
     *
     */
	public static DefaultMutableTreeNode addTreeNode(JTree tree,Object child) {
        DefaultMutableTreeNode parentNode = null;
        TreePath parentPath = tree.getSelectionPath();

        if (parentPath == null) {
	        parentNode = (DefaultMutableTreeNode)((DefaultTreeModel)tree.getModel()).getRoot();
        } else {
            parentNode = (DefaultMutableTreeNode)
                         (parentPath.getLastPathComponent());
        }
        return addTreeNode(tree,parentNode, child, true);
    }

	public static DefaultMutableTreeNode addTreeNode(JTree tree,String code,String name) {
        return addTreeNode(tree, new CodeNameBean(code,name));
    }
	
	public static DefaultMutableTreeNode addTreeNode(JTree tree,DefaultMutableTreeNode parent,
                                            Object child) {
        return addTreeNode(tree,parent, child, false);
    }

	public static DefaultMutableTreeNode addTreeNode(JTree tree,DefaultMutableTreeNode parent,
                                            Object child, 
                                            boolean shouldBeVisible) {
        DefaultMutableTreeNode childNode = 
                new DefaultMutableTreeNode(child);

        if (parent == null) {
            parent = (DefaultMutableTreeNode)((DefaultTreeModel)tree.getModel()).getRoot();
        }

        ((DefaultTreeModel)tree.getModel()).insertNodeInto(childNode, parent, 
                                 parent.getChildCount());

        //Make sure the user can see the lovely new node.
        if (shouldBeVisible) {
            tree.scrollPathToVisible(new TreePath(childNode.getPath()));
        }
        return childNode;
    }

	/**
	 * 获取当前选择的树节点的内部代码
	 * @return 当前选择的树节点的内部代码,如果当前没有选择,return null.
	 */
	public static String getSelectedTreeNodeCode(JTree tree) {
		if(tree==null)
			return null;
		try{
			return ((CodeNameEntity) ((DefaultMutableTreeNode) tree
				.getLastSelectedPathComponent()).getUserObject()).getCode();
		
		} catch (NullPointerException e){
			return null;
		}
	}

	/**
	 * 获取当前选择的树节点的内部代码集合
	 * @param tree
	 * @return 当前选择的树节点的内部代码集合
	 */
	public static Vector<String> getSelectedTreeNodeCodes(JTree tree) {
		if(tree==null)
			return null;
		
        TreePath[] currentSelection = tree.getSelectionPaths();
        Vector<String> vector=null;
        if (currentSelection != null) {
        	vector=new Vector<String>();
        	DefaultMutableTreeNode currentNode = null;
        	for (int i = 0; i < currentSelection.length; i++) {
        		if(currentSelection[i]==null)
        			continue;
                currentNode = (DefaultMutableTreeNode)(currentSelection[i].getLastPathComponent());
                vector.add(((CodeNameEntity)currentNode.getUserObject()).getCode());				
			}
        }
        return vector;
	}


	/******************************************************************
	 * 
	 * 			for JTable component.
	 * 
	 * ****************************************************************/
	
	/**
	 * initialize a Table Component according to the sql string. It will not initialize the table header,
	 * 		so must insure that the table header has been initialized before call this function.
	 * @param table JTable Object be initialized
	 * @param ps_sql sql statement
	 */
	public static void initTable(JTable table, String ps_sql) {
		initTable(table,ps_sql,false);
	}
	
	/**
	 * initialize a Table Component data and it's header information.
	 * @param table JTable Object be initialized
	 * @param ps_sql sql statement
	 * @param addTableHeader need to set ColumnIdentifiers or not,the default value is false.
	 */
	public static void initTable(JTable table, String ps_sql,boolean addTableHeader) {
		if (table == null || ps_sql == null) {
			return;
		}
	    Connection conn=null;
	    Statement stmt=null;
	    ResultSet rs=null;
	    ResultSetMetaData  rsmd=null;
	    
	    DefaultTableModel dtm=null;
	    if(table.getModel() instanceof DefaultTableModel ){
	    	dtm=(DefaultTableModel)table.getModel();
	    	
	    }else if(table.getModel() instanceof PlainTableModel){
	    	dtm=((PlainTableModel)table.getModel()).getTableModel();
	    }else{
	    	dtm = new DefaultTableModel();
	    }
	    // removeAllRows
    	int rowCount=dtm.getRowCount();
    	//System.out.println("rowCount="+rowCount); //?不是返回当前行数，而是将来的行数？
    	for (int i = 0; i < rowCount; i++) {
    		//System.out.println("remove i="+i);
    		dtm.removeRow(0);
		}
    	
	    try {
			conn=getConnection();
			stmt=conn.createStatement();
			rs=stmt.executeQuery(ps_sql);
			Vector<Object> v_rowData=new Vector<Object>();
			rsmd=rs.getMetaData();
			int k=rs.getMetaData().getColumnCount();
			
			//table header
			if(addTableHeader){					
				for (int i = 1; i <= k; i++) {
					v_rowData.add(rsmd.getColumnName(i));
				}
				dtm.setColumnIdentifiers(v_rowData);
			}
			
			//table data
			while(rs.next()){
				v_rowData = new Vector<Object>();
				for (int i = 1; i <= k; i++) {
					Object obj = rs.getObject(i);
					//System.out.println( obj );
					v_rowData.add( obj );
				}
				dtm.addRow(v_rowData);
			}
			//table.settableData(vector);
			//table.setModel( dtm );
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			wzw.util.DbUtils.closeQuietly(conn, stmt, rs);
		}		
		
	}
	
	/******************************************************************
	 * 
	 * 			for all component,mainly for frame,dialog.
	 * 
	 * ****************************************************************/

	/**
	 * <p>设置显示对象到中心位置.</p>
	 * @param parent 中心的参考对象
	 * @param current 要移动到中心的对象
	 */
	public static void setLocationToCenter(Component parent,Component current){
		current.setLocation(parent.getLocationOnScreen().x + (parent.getWidth() - current.getWidth()) / 2, 
							parent.getLocationOnScreen().y + (parent.getHeight() - current.getHeight()) / 2);
		
	}

	/**
	 * <p>没有指定父对象时，设置显示对象到屏幕的中央.
	 * 		注意：这里屏幕的宽度没有除去系统任务栏/开始菜单托盘的高度，隐藏操作系统托盘时效果最佳。</p>
	 * @param parent 显示的父对象，即显示在那个容器上
	 * @param current 要移动到屏幕中心的对象
	 * @param dimension 有时候对象宽度高度获取不正确，可以通过这里传入
	 */
	public static void setLocationToCenter(Component current){
		Dimension dimension = null;
		setLocationToCenter(current , dimension); 
	}
	public static void setLocationToCenter(Component current, Dimension dimension){
		Component parent = null;
		if( current instanceof JComponent){
			parent = ((JComponent)current).getTopLevelAncestor();
		}
		if(parent!=null){
			current.setLocation(parent.getLocationOnScreen().x + (parent.getWidth() - current.getWidth()) / 2, 
							parent.getLocationOnScreen().y + (parent.getHeight() - current.getHeight()) / 2);
		} else {
		    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
			Dimension fs = dimension;
			if(fs==null){
			    fs = current.getSize();
			}
		    if (fs.height > d.height) fs.height = d.height;
		    if (fs.width > d.width)   fs.width = d.width;
		    current.setLocation((d.width - fs.width) / 2,
		                      (d.height-20 - fs.height) / 2);	//20 is system toolbar height		
		}
	}


	 /**
	  * 设置当前外观为 本地显示风格外观,Java默认的跨平台外观,Motif/CDE外观.
	  * @param style 风格值
	  * @param c 应用风格外观的Compoment对象
	  */
	 public static void setLookAndFeel(String style,Component c) {
		 try {
			 if(style==null) return ;
			 
			 if(style.equals( DirectorConstants.LookAndFeel_Current )){
				 UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
			 
			 } else if(style.equals( DirectorConstants.LookAndFeel_Windows )){
				 UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
			 
			 } else if(style.equals( DirectorConstants.LookAndFeel_Metal )){
				 UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName() );
			 
			 } else if(style.equals( DirectorConstants.LookAndFeel_Motif )){
				 UIManager.setLookAndFeel( ComponentUtil.getNimbusLookAndFeelClassName() );//Nimbus风格，新出来的外观，jdk6 update10版本以后的才会出现
				 //UIManager.setLookAndFeel( ComponentUtil.getMotifLookAndFeelClassName() );
			 }
			 if( c!=null ){
				 SwingUtilities.updateComponentTreeUI( c );
				//c.repaint();
				//c.doLayout();
			 }
			 
		 } catch(Throwable e) {
			 System.out.println("Error setting Java LAF: " + e.getMessage() );//by wzw
		 }
	 }

	public static String getNimbusLookAndFeelClassName() {
		return "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";
	}
	public static String getMotifLookAndFeelClassName() {
		return "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
	}

	public static void setLookAndFeel(String style) {
		setLookAndFeel(style, null);
	}

	/******************************************************************
	 * 
	 * 			else.
	 * 
	 * ****************************************************************/
	 
	 /**
	  * 获取数据库的连接
	  */
	public static Connection getConnection() throws SQLException{		
		return ApplicationContext.getInstance().getDataSourceManager().getConnection(ComponentUtil.poolName);
	}

	public static void setSizeToNormal(Component current) {
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int height = (int) screenSize.getHeight();
		height = height>=900?900:750;
		int width = height/3*4;
		current.setSize(width, height);
	}

}

